package sites.electrozine.tags;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;

import core.HtmlMapper;
import core.HtmlServices;
import core.ISiteMapper;

public class ProductInfoEzTag implements ISiteMapper {

    private String pid;
    private String baseUrl = "http://www.electrozine.be/";

    /**
     * find all h4 nodes that contain text ProductBeschrijving next sibling
     * nodes are the descripton items. They will be listed in <item> tags.
     */
    @HtmlMapper(xpath = "//a[contains(@href, 'fabdetail.php')]")
    private String manufact;

    @HtmlMapper(xpath = "//h4[contains(text(),'Product')]/following-sibling::text()")
    private List<String> productDescription = new ArrayList<String>();

    @HtmlMapper(xpath = "//h4[contains(text(),'Eigen')]/following-sibling::ul/li", outputType = HtmlMapper.OUTPUT_XML)
    private List<String> productProperties = new ArrayList<String>();

    @HtmlMapper(xpath = "//h3/following-sibling::text()")
    private String productDescr;

    // @HtmlMapper(xpath = "/html/head/meta")
    // private List<Meta> meta = new ArrayList<Meta>();

    @HtmlMapper(xpath = "//html/body/div/table/tr/td/div/div/table/tr/td/div/div[@style = 'margin-bottom:40px;']/form")
    private String price;

    @HtmlMapper(xpath = "//div[@id='kruimels']//a[contains(@href, 'producten.php?hcat')]")
    private String headCat;

    @HtmlMapper(xpath = "//div[@id='kruimels']//a[contains(@href, 'producten.php?scat')]")
    private String subCat;

    @HtmlMapper(xpath = "//h1")
    private String title;

    @HtmlMapper(xpath = "//img[contains(@src, 'ez_prod')][not(contains(@src, 'tn'))]/@src")
    private List<String> images = new ArrayList<String>();

    /************************** ADDITIONAL METHODS ***************************************/

    public List<String> getkeywords() {
        List<String> keywords = new ArrayList<String>();

        /*
         * for (Meta m : meta) { if ("keywords".equalsIgnoreCase(m.getName())) {
         * StringTokenizer st = new StringTokenizer(m.getContent(), ","); while
         * (st.hasMoreTokens()) { keywords.add(st.nextToken()); } } }
         */
        return keywords;
    }

    public String getPrice() {
        if (price == null) return "";
        Pattern pattern = Pattern.compile("([0-9]*),([0-9]*)");
        Matcher match = pattern.matcher(price);
        if (match.find()) {
            if(match.group(2).equals(""))
                return match.group(1);
            return match.group(1) + "." + match.group(2);
        }
        return null;

    }

    public String getProductPropertiesClean() {

        StringBuffer sb = new StringBuffer();

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db;
            db = dbf.newDocumentBuilder();

            XPathFactory factory = XPathFactory.newInstance();

            XPath xpath = factory.newXPath();
            XPathExpression expr;

            XPath xpathr = factory.newXPath();
            XPathExpression exprr;

            expr = xpath.compile("//b");
            exprr = xpath.compile("//li");
            if (getProductProperties().size() > 0) sb.append("<product><specs>");
            for (String s : getProductProperties()) {

                // parse using builder to get DOM representation of the XML file
                // System.out.println(s);

                Document doc = db.parse(new ByteArrayInputStream(s.getBytes("UTF-8")));

                String result = (String) expr.evaluate(doc, XPathConstants.STRING);
                if ("".equals(result) || result == null) {
                    sb.append("<item>" + exprr.evaluate(doc, XPathConstants.STRING) + "</item>\n");
                }
                else
                    sb.append("<title>" + result + "</title>\n");
            }
            if (getProductProperties().size() > 0) sb.append("</specs></product>");
            return sb.toString();
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return sb.toString();
    }

    public String getProductDescriptionString() {
        StringBuilder sb = new StringBuilder();
        if (getProductDescription().size() > 0) sb.append("<ul class=\"descr\">");
        for (String s : getProductDescription()) {
            sb.append("<li>" + s + "</li>");
        }
        if (getProductDescription().size() > 0) sb.append("</ul>");
        return sb.toString().trim();
    }

    private void createProductDetailScript(OutputStream out) {

        StringBuffer sb = new StringBuffer();
        sb.append("insert into products(pid, \n\t price, \n\t description, \n\t manufactor, \n\t title, \n\t category, \n\t subcategory, \n\t tag, \n\t properties) \n values ( \n\t");
        sb.append("'" + pid + "',\n\t'" + escapeChars(getPrice()) + "',\n\t'" + escapeChars(getProductDescriptionString()) + "',\n\t'" + escapeChars(getManufact()) + "',\n\t'" + escapeChars(getTitle()) + "',\n\t'" + escapeChars(getHeadCat()) + "',\n\t'" + escapeChars(getSubCat()) + "',\n\t'" + escapeChars(getProductDescr()) + "',\n\t'" + escapeChars(getProductPropertiesClean()) + "');\n");
        try {
            out.write(sb.toString().getBytes("UTF-8"));
        }
        catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void saveImages(Writer out) {

        try {
            int i = 1;
            for (String s : getImages()) {
                String filename = title + "-" + i++ + ".jpg";
                String path = "products/images/";
                filename = HtmlServices.saveImage(new URL(baseUrl + s.substring(3)), path, filename);

                String query = "INSERT INTO PRODUCT_IMAGES(pid, imagepath)VALUES('" + pid + "','" + filename + "');\n";
                out.write(query);
                out.flush();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String escapeChars(String str) {
        if (str == null) return "";
        return str.replaceAll("'", "\\\\'");
    }

    /******************************** GENERATED CODE ***************************************/
    public List<String> getProductDescription() {
        return productDescription;
    }

    public void setProductDescription(List<String> productDescription) {
        this.productDescription = productDescription;
    }

    public void addProductDescription(String productDescription) {
        this.productDescription.add(productDescription);
    }

    /*
     * public List<Meta> getMeta() { return meta; } public void
     * setMeta(List<Meta> meta) { this.meta = meta; } public void addMeta(Meta
     * meta) { this.meta.add(meta); }
     */
    public void setPrice(String price) {
        this.price = price;
    }

    public String getManufact() {
        return manufact;
    }

    public void setManufact(String manufact) {
        this.manufact = manufact;
    }

    public String getHeadCat() {
        return headCat;
    }

    public void setHeadCat(String headCat) {
        this.headCat = headCat;
    }

    public String getSubCat() {
        return subCat;
    }

    public void setSubCat(String subCat) {
        this.subCat = subCat;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<String> getProductProperties() {
        return productProperties;
    }

    public void setProductProperties(List<String> productProperties) {
        this.productProperties = productProperties;
    }

    public void addProductProperties(String productProperties) {
        this.productProperties.add(productProperties);
    }

    public String getProductDescr() {
        return productDescr;
    }

    public void setProductDescr(String productDescr) {
        this.productDescr = productDescr;
    }

    public List<String> getImages() {
        return images;
    }

    public void setImages(List<String> images) {
        this.images = images;
    }

    public void addImages(String images) {
        this.images.add(images);
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    @Override
    public void generateScript(Writer out) {
        StringBuffer sb = new StringBuffer();
         sb.append("insert into tmp_ez_products(pid, \n\t price, \n\t description, \n\t manufactor, \n\t title, \n\t category, \n\t subcategory, \n\t tag, \n\t properties) \n values ( \n\t");
         sb.append("'" + pid + "',\n\t'" + escapeChars(getPrice()) + "',\n\t'"
         + escapeChars(getProductDescriptionString()) + "',\n\t'" +
         escapeChars(getManufact()) + "',\n\t'" + escapeChars(getTitle()) +
         "',\n\t'" + escapeChars(getHeadCat()) + "',\n\t'" +
         escapeChars(getSubCat()) + "',\n\t'" + escapeChars(getProductDescr())
         + "',\n\t'" + escapeChars(getProductPropertiesClean()) + "');\n");
        //saveImages(out);
        try {
            out.write(sb.toString());
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /*
     * @Override public Class<? extends Annotation> annotationType() { // TODO
     * Auto-generated method stub return null; }
     * @Override public String xpath() { // TODO Auto-generated method stub
     * return null; }
     */
}
